/**************************************************************************
 * @doc PIP
 * @module isoutl.C |
 * Source code used to communicate via the ISO8583 Mesaage Engine and the PIP Engine.
 *
 * Product     :   SoftPay 2000 (Global Payment Methodology).
 * <nl>Developer   :
 * <nl>Notes       :
 *
 * @head3 PIP & ISO Functions |
 * @index | PIP
 * @end
 *
 * Copyright (c) 1996-2000 by VeriFone Inc. All rights reserved.
 *
 * No part of this software may be used, stored, compiled, reproduced,
 * modified, transcribed, translated, transmitted, or transferred, in any form
 * or by any means whether electronic, mechanical, magnetic, optical,
 * or otherwise, without the express prior written permission of VeriFone, Inc.

$Log: /SoftPay/SPK2SIM/Source/PIP/isoutl.c $
**************************************************************************/

#include <project.h>
#define VSISUT_C

#include <aclconio.h>
#include <stdio.h>
#include <stdlib.h>
#include <acldev.h>
#include <aclutil.h>
#include <message.h>
#include <aclstr.h>
#include <applidl.h>
#include <xmodem.h>
#include <iso8583.h>
#include <amexhost.h>
#include <dbmgr.h>
#include <string.h>
#include <svc.h>
#include <print.h>

#ifdef PIP_DEFINED

#ifdef DEBUG_VSISOUTL
#define DEBUG_95
#endif

#include <define.h>
#include <isodefs.h>
#include <transact.h>
#include <funcids.h>
#include <table.h>
#include <operate.h>
#include <bmp.h>
#include <pipmsg.h>
#include <packet.h>
#include <modem.h>
#include <mdmdefs.h>
#include <modemmsg.h>
#include <msgfuncs.h>
#include <spdebug.h>
#include <isoload.h>
#include <mem.h>
#include <isoutl.h>
#include <ifldtbl.h>
#include <format.h>
#include <revutl.h>
#include <hdt.h>
#include <cdt.h>
#include <ui.h>
#include <codesec.h>

#include "..\ISODump\ISODump.h"

COMM_8583_DATA* psrCommData;
HOST_8583_DATA* psrHostData;
VALIDATION_STRUCT srInputValStruct;
//This buffer is declared because it must be a static global and not allocated in
//psrCreateCommData. This will go away when the ACT library function asm_8583_rec()
//no longer sets the application allocated reversal buffer to the global buffer
//defined in the library
unsigned char reversal_buffer[512];

unsigned char stMap8583[BIT_MAP_SIZE];
unsigned char stRevFileName[FILENAME_SIZE + 1];

FUNCTION_TABLE srPIPISOFuncs[] = {
    {(PFI_TO) inDefaultSetTransFields,              SET_TRANS_FIELDS},
    {(PFI_TO) inDefaultInitValidationStruct,         INIT_VALIDATION_STRUCT},
    {(PFI_TO) inDefaultUpdateReversal,              UPDATE_REVERSAL},
    {(PFI_TO) inDefaultResetCommData,               RESET_COMM_DATA_FIELDS},
    {(PFI_TO) inDefaultResetHostData,               RESET_HOST_DATA_FIELDS},
    {0,                                     END_OF_FUNC_TABLE},

};

/*********************************************************************************************
* @func int | inAddPIPISOFunctions |
*       Adds PIPISO functions to the flexi record.
*
* @rdesc return values.
* @flag int    |  VS_ERR, VS_ESCAPE or VS_SUCCESS
* @end
**********************************************************************************************/

int inAddPIPISOFunctions(void) {
    int inCount = 0;

    /* Add PIPISO functions to the flexi record */
    do {
        if (inAddFunctionPointer(srPIPISOFuncs[inCount].inFieldID, srPIPISOFuncs[inCount].pinFunction) == VS_ERR)
            return (VS_ERR);
        inCount++;
    } while (srPIPISOFuncs[inCount].inFieldID != END_OF_FUNC_TABLE);

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func void |  inSetTransFields |
*
* @parm TRANSACTION_OBJECT * | pobTran |                This is the transaction object.
* @parm int  | host |
* @parm unsigned int | inTransCode |
* @parm char * | szProcCode |
*
* @end
**********************************************************************************************/

typedef int (*PFI_TO_INT_SH_PSZ)(TRANSACTION_OBJECT*,int,unsigned short,char*);

int inSetTransFields(TRANSACTION_OBJECT* pobTran,int host,unsigned short shTransCode,char* szProcCode) {
    int inRetVal = VS_ERR;
    PFI_TO_INT_SH_PSZ pinSetTransFields;

    if ((pinSetTransFields = (PFI_TO_INT_SH_PSZ) inGetFunctionPointer(SET_TRANS_FIELDS)) != NULL)
        inRetVal = pinSetTransFields(pobTran, host, shTransCode, szProcCode);

    return (inRetVal);
}

int inDefaultSetTransFields(TRANSACTION_OBJECT* pobTran,int host,unsigned short  shTransCode,char* szProcCode) {
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inUpdateReversal |
*           Gets and call the host defined ACT callback function which can
*           change the values of any field in the reversal packet.
*
* @parm  COMM_8583_DATA *| srCommStruct |
*        The comm data structure containing the reversal data
*
* @end
**********************************************************************************************/

typedef int (*PFI_COMM)(COMM_8583_DATA*);

int inUpdateReversal(COMM_8583_DATA* srCommStruct) {
    PFI_COMM pinUpdateReversal;

    if ((pinUpdateReversal = (PFI_COMM) inGetFunctionPointer(UPDATE_REVERSAL)) != NULL)
        pinUpdateReversal(srCommStruct);
    return (VS_SUCCESS);
}

int inDefaultUpdateReversal(COMM_8583_DATA* srCommStruct) {
    return (VS_SUCCESS);
}

/*********************************************************************************************
* @func void |  vdInitializeValidationStruct |
* Initializes the validation structure.
*
* @parm TRANSACTION_OBJECT * | pobTran |                        This is the transaction object.
* @parm VALIDATION_STRUCT *  | psrValidationParameters |
*
* @end
**********************************************************************************************/

typedef int (*PFI_TO_VS)(TRANSACTION_OBJECT*,VALIDATION_STRUCT*);

void vdInitializeValidationStruct(TRANSACTION_OBJECT* pobTran,VALIDATION_STRUCT* psrValidationParameters) {
    PFI_TO_VS pinInitializeValidationStruct;

    if ((pinInitializeValidationStruct = (PFI_TO_VS) inGetFunctionPointer(INIT_VALIDATION_STRUCT)) != NULL)
        pinInitializeValidationStruct(pobTran, psrValidationParameters);
}

/*********************************************************************************************
* @func int |  inDefaultInitValidationStruct |
* Initializes the validation structure.
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       This is the transaction object.
*
* @parm VALIDATION_STRUCT * | psrValidationParameters |
*       Validation structure.
*
* @end
**********************************************************************************************/

int inDefaultInitValidationStruct(TRANSACTION_OBJECT* pobTran,VALIDATION_STRUCT* psrValidationParameters) {
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int |  inResetCommDataFields |
*
*
* @end
**********************************************************************************************/

int inResetCommDataFields() {
    int inRetVal = VS_ERR;
    PFI_VOID pinResetCommData;

    if ((pinResetCommData = (PFI_VOID) inGetFunctionPointer(RESET_COMM_DATA_FIELDS)) != NULL_PFI)
        inRetVal = pinResetCommData();
    return(inRetVal);
}

int inDefaultResetCommData() {
    return(VS_SUCCESS);
}


/*********************************************************************************************
* @func void | vdFreeCommData |
*       Deallocates the memory for communication data structure
*
* @parm COMM_8583_DATA | *psrCommData |
*       Communication data structure
*
* @end
**********************************************************************************************/
void vdFreeCommData(COMM_8583_DATA* psrCommData) {
    vdFree((char *) psrCommData->receive);
    //This buffer is a static global buffer and not allocated. Therefore, is is not freed.
    //This will go away when the ACT library function asm_8583_rec()
    //no longer sets the application allocated reversal buffer to the global buffer
    //defined in the library
    //    vdFree((char *)psrCommData->reversal);
    vdFree((char *) psrCommData->transmit);
    vdFree((char *) psrCommData);
}

/*********************************************************************************************
* @func COMM_8583_DATA* | psrCreateCommData |
*       Allocates memory for the communication data structure. Also initializes it.
*
* @parm TRANSACTION_OBJECT *| pobTran |
*       Transaction object
* @parm int | inISOSendSize |
*       Maximum size of the request packet
* @parm VS_BOOL | fReversalFlag |
*       Reversal flag
* @rdesc return values.
* @flag COMM_8583_DATA* |  A pointer to the Communication data structure
* @end
**********************************************************************************************/

COMM_8583_DATA* psrCreateCommData(TRANSACTION_OBJECT* pobTran,int inISOPacketSize,VS_BOOL fReversalFlag) {
#ifdef MODEM
    MODEM_OBJECT* obModem;
#endif /* MODEM */

    if ((psrCommData = (COMM_8583_DATA *) pchAlloc(sizeof(COMM_8583_DATA))) == NULL_CH)
        return ((COMM_8583_DATA *) NULL_CH);

    if ((psrCommData->transmit = (unsigned char *) pchAlloc(inISOPacketSize)) == NULL_CH)
        return ((COMM_8583_DATA *) NULL_CH);

    //This buffer is set to the static global buffer and not allocated to prevent a memory
    //leak when the pointer value is changed and then the allocated buffer was not freed.
    //This will go away when the ACT library function asm_8583_rec()
    //no longer sets the application allocated reversal buffer to the global buffer
    //defined in the library
    //    if( (psrCommData->reversal = (unsigned char *)pchAlloc(inISOPacketSize)) == NULL_CH)
    //          return ((COMM_8583_DATA *)NULL_CH);
    psrCommData->reversal = reversal_buffer;

    if ((psrCommData->receive = (unsigned char *) pchAlloc(inISOPacketSize)) == NULL_CH)
        return ((COMM_8583_DATA *) NULL_CH);

#ifdef MODEM
    obModem = (MODEM_OBJECT *) obCommunication.Data;
    psrCommData->comm_handle = &obModem->hModem;
#endif /* MODEM */

    psrCommData->p_fld_table = srBaseIsoFDT;
    psrCommData->comm_timeout = 30;
    psrCommData->wait_for_carrier = 30;
    psrCommData->map = stMap8583;
    psrCommData->validation = (PFI_VD_INT) inBaseRespValidation;
    psrCommData->v_parms_size = STRUCT_OFFSET(srInputValStruct, b_rrn[0]) + sizeof(srInputValStruct.b_rrn);

    psrCommData->v_parms = (void *) &srInputValStruct,

    psrCommData->transceiver = inTxRx8583;

    psrCommData->transmit_size = inISOPacketSize + sizeof(VALIDATION_STRUCT) + 1;
    psrCommData->transmit_limit = inISOPacketSize;

    psrCommData->receive_size = inISOPacketSize;
    psrCommData->receive_limit = inISOPacketSize;

    psrCommData->reversal_size = inISOPacketSize + sizeof(VALIDATION_STRUCT) + 1;
    psrCommData->reversal_limit = inISOPacketSize;

    psrCommData->base_fname = stRevFileName;

    psrCommData->rev_msg_id[0] = 0x04;
    psrCommData->rev_msg_id[1] = 0x00;

    inResetCommDataFields();        /* Overload function to change fields in the comm data struct */
    vdInitializeValidationStruct(pobTran, &srInputValStruct);

    return(psrCommData);
}


/*********************************************************************************************
* @func int |  inResetHostDataFields |
*
*
* @end
**********************************************************************************************/

int inResetHostDataFields() {
    int inRetVal = VS_ERR;
    PFI_VOID pinResetHostData;

    if ((pinResetHostData = (PFI_VOID) inGetFunctionPointer(RESET_HOST_DATA_FIELDS)) != NULL_PFI)
        inRetVal = pinResetHostData();
    return(inRetVal);
}

int inDefaultResetHostData() {
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func void | vdFreeHostData |
*       Deallocates memory used for the host ISO HOST data structure.
*
* @parm HOST_8583_DATA | *psrHostData |
*       Host data structure
*
* @end
**********************************************************************************************/
void vdFreeHostData(HOST_8583_DATA* psrHostData) {
    vdFree((char *) psrHostData->work_buf);
    vdFree((char *) psrHostData);
}

/*********************************************************************************************
* @func void | vdFreeISO8583Data |
*       Deallocates memory used for the variant structures in fields 60 and 63.
*       No Parameters and no return values.
*
*
* @end
**********************************************************************************************/

void vdFreeVariantTables() {
    vdFree((char *) psrVariant60);
    psrVariant60 = NULL;
    vdFree((char *) psrVariant63);
    psrVariant63 = NULL;
}

/*********************************************************************************************
* @func HOST_8583_DATA* | psrCreateHostData |
*       Allocates memory for the host ISO HOST data structure. Also initializes it.
*
* @rdesc return values.
* @flag HOST_8583_DATA* |  A pointer to the host data structure
* @end
**********************************************************************************************/
HOST_8583_DATA* psrCreateHostData() {
    if ((psrHostData = (HOST_8583_DATA *) pchAlloc(sizeof(HOST_8583_DATA))) == NULL_CH)
        return ((HOST_8583_DATA *) NULL_CH);

    if ((psrHostData->work_buf = (unsigned char *) pchAlloc(100)) == NULL_CH)
        return ((HOST_8583_DATA *) NULL_CH);

    psrHostData->host_num = 0;
    psrHostData->advice_flag = 1;
    psrHostData->dcp_flag = 1;
    psrHostData->reverse_flag = 1;
    psrHostData->optional_map = stOptionalMap;
    psrHostData->key = srISO.pszField62;
    psrHostData->c8583_data = (COMM_8583_DATA *) NULL_CH;

    inResetHostDataFields();    /* Overload function to change fields in the host data struct */
    return (psrHostData);
}

/*********************************************************************************************
* @func int | inLoadTransData |
*       This routine takes care of loading all the fields
*       corresponding to this transaction with the actual data.
*       To be called before the actual Pack/Unpack process begins.
*
* @parm TRANSACTION_OBJECT * | pobTran |
*       Transaction object
* @parm char * | pstBitMap |
*       Bitmap for the transaction
* @parm void *| pvLoadFuncs[])() |
*       Array of functions which load the data fields in the field table
*
* @rdesc return values.
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

typedef void (*PVOID_TO)(TRANSACTION_OBJECT*);

int inLoadTransData(TRANSACTION_OBJECT* pobTran,char* pstBitMap,ISOLOAD* psrLoadFuncs) {
    int inLoop;
    char* pucByte;
    unsigned char ucBitSelector;
    int inBitMapIndex;
    char btFieldNum = 1;
    ISOLOAD* psrISOLoad;
    PVOID_TO pvdFunction;

    psrISOLoad = psrLoadFuncs;
    pucByte = pstBitMap;
    /* Load the values for the fields present in the bit map */
    for (inBitMapIndex = 0; inBitMapIndex < 8; inBitMapIndex++, pucByte++) {
        ucBitSelector = 0x80;
        for (inLoop = 0; inLoop < 8; inLoop++, ucBitSelector >>= 1, btFieldNum++) {
            if (*pucByte & ucBitSelector) {
                while (psrISOLoad->btFieldNum < btFieldNum) {
                    psrISOLoad++;
                }
                if (psrISOLoad->btFieldNum == btFieldNum) {
                    pvdFunction = psrISOLoad->vdLoad;
                    (pvdFunction) (pobTran);
                } else
                    *pucByte &= ~ucBitSelector;
            }
        }
    }

    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inGetBitmapRecord |
*       This routine reads through the bmp file to find the record
*       that corresponds the transaction code.
*
* @parm BMP_REC * | psrBMPRec|
*       The bmp file record
* @parm int| inTransCode |
*       Transaction code
*
* @rdesc return values.
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/

int inGetBitmapRecord(BMP_REC* psrBMPRec,short shTransCode) {
    char szFName[FILENAME_SIZE + 1];
    int inRetVal = VS_SUCCESS;
    int hFHandle;
    char stVerInfo[GEN_VER_SIZE];
    int inResult;
    char szErrorString[MESSAGE_SIZE];


    MEMCLR(szErrorString, sizeof(szErrorString));
    MEMCLR(szFName, sizeof(szFName));
    strcpy(szFName, szGetHostFileName());
    strcat(szFName, ISOBMP_FNAME);

    if ((hFHandle = open(szFName, O_RDONLY)) == -1) {
        vdGetMessageFromThisFile(PIP_MESSAGE_FILE, BMP_FILE_OPEN_ERR_MSG, szErrorString);
        vdDisplayErrorString(szErrorString);
        return(VS_ERR);
    }

    /* Skip GENDATA version header information */
    if (read(hFHandle, stVerInfo, GEN_VER_SIZE) != GEN_VER_SIZE) {
        close(hFHandle);
        vdGetMessageFromThisFile(PIP_MESSAGE_FILE, BMP_FILE_READ_ERR_MSG, szErrorString);
        vdDisplayErrorString(szErrorString);
        return(VS_ERR);
    }

    do {
        inResult = read(hFHandle, (char *) psrBMPRec, sizeof(BMP_REC));
        if (inResult == 0) {
            inRetVal = VS_ERR;

            vdGetMessageFromThisFile(PIP_MESSAGE_FILE, BMP_FILE_READ_ERR_MSG, szErrorString);
            vdDisplayErrorString(szErrorString);
            break;                           /* End of file reached */
        }
        if (inResult != sizeof(BMP_REC))        /* or even result = -1 */ {
            inRetVal = VS_ERR;

            vdGetMessageFromThisFile(PIP_MESSAGE_FILE, BMP_FILE_READ_ERR_MSG, szErrorString);
            vdDisplayErrorString(szErrorString);
            break;          /* Read error, get out */
        }

        if (psrBMPRec->shTranCode == shTransCode) //Tran code found
            break;
    } while (1);

    if (close(hFHandle) < 0)
        inRetVal = VS_ERR;

    return(inRetVal);
}

/*********************************************************************************************
* @func int | inLoadBitmap |
*       This routine converts the fields in the bmp record from strings
*       to arrays of hex values.
*
* @parm int| inTransCode |
*       Transaction code
* @parm unsigned char *| btMti |
*       Message type index
* @parm unsigned char *| btMap8583 |
*       Bit Map
* @parm unsigned char *| btProcCode |
*       Processing code
*
* @rdesc return values.
* @flag int    |  VS_SUCCESS
* @end
**********************************************************************************************/


int inLoadBitmap(unsigned short shTransCode,unsigned char* btMti,unsigned char* btMap8583,unsigned char* btProcCode) {
    BMP_REC srBMP;

    //pdebug(("--inLoadBitmap--"));
    //pdebug(("inTransCode = %d", inTransCode));


    if (inGetBitmapRecord(&srBMP, shTransCode) != VS_SUCCESS)
        return(VS_ERR);

    if (strlen(srBMP.szMti) != 0) {
        strupr(srBMP.szMti);
        SVC_DSP_2_HEX(srBMP.szMti, (char *) btMti, MTI_SIZE);
    }

    if (strlen(srBMP.szBitmap) != 0) {
        strupr(srBMP.szBitmap);
        SVC_DSP_2_HEX(srBMP.szBitmap, (char *) btMap8583, BIT_MAP_SIZE);
    }

    if (strlen(srBMP.szProcCode) != 0) {
        strupr(srBMP.szProcCode);
        SVC_DSP_2_HEX(srBMP.szProcCode, (char *) btProcCode, PROC_CODE_SIZE);
    }
    return(VS_SUCCESS);
}

/*********************************************************************************************
* @func int | inTxRx8583 |
*           This routine will :
*                -> Check to see whether the Carrier has been established.
*                -> If not, wait until carrier is established, till time-out, or abort.
*                -> Send the request packet over the modem port.
*                -> Wait till the response is received at the modem port, or time-out.
*
* @parm int | inModem|
*       Handle to the Open Modem Device
* @parm int | inMode|
*       Transmit and Receive OR receive only
* @parm unsigned char * | pstReqBuf|
*       The address of the source buffer
* @parm unsigned int | inReqSiz|
*       The size of the request Packet
* @parm unsigned char * | pstRespBuf|
*       Address of the buffer where the response is stored
* @parm unsigned int | inRespSiz|
*       Maximum size of response
* @parm unsigned int |inRespTimeout|
*       Time within which response is to be received
* @parm unsigned int | inCarrierTimout
*       Time within which carrier is to be establised
*
* @rdesc return values.
* @flag int    | -> TR_CLR_KEY   Abort while waiting for Carrier.
*                -> TR_WR_FAIL   Write to Modem Failed.
*                -> TR_LOST_CARRIER Carrier Lost while waiting for response.
*                -> TR_TO_RESP   Timeout while waiting for response.
*                -> TR_RD_FAIL   Read from Modem Fail.
*                -> Sucess with the Number of bytes read from the Modem Port.
*
* @end
**********************************************************************************************/

int (*transceiver) (int,int,unsigned char*,unsigned,unsigned char*,unsigned,unsigned,unsigned);
int inTxRx8583(int inModem,/* Handle to the Open Modem Device */
    int inMode,/* Transmit and Receive OR receive only */
    unsigned char* pstReqBuf,/* The address of the source buffer */
    unsigned int inReqSiz,/* The size of the request Packet */
    unsigned char* pstRespBuf,/* Address of the buffer where the response is stored */
    unsigned int inRespSiz,/* Maximum size of response */
    unsigned int inRespTimeout,/* Time within which response is to be received */
    unsigned int inCarrierTimout)        /* Time within which carrier is to be establised */ {
    PACKET_OBJECT obPacket;
    int inRetVal = VS_TRUE;                                  /*Check if Carrier is Up */
    VS_BOOL fCarrierPresent = VS_TRUE;
    int inTimeOut;
    char szSourceReversalFileName[20];
    char szDestReversalFielName[20];

    #ifdef PRINTISO_DEFINED
    int inPrintISO = get_env_int("PRNTISO"); //jrd 01052004
    #endif /* PRINTISO_DEFINED */


    // ASPAC needs to do a reversal even after response is received if
    // powerfail occurs in Analyze response.  EM58250/ASPAC bug # 10,14 & 65
    memset(szSourceReversalFileName, 0x00, sizeof(szSourceReversalFileName));
    vdGetReversalFileName(szSourceReversalFileName, inGetHostIndex());
    sprintf(szDestReversalFielName, "%s%s", szSourceReversalFileName, BACKUP_REV_FILE_EXTN);
    strcat(szSourceReversalFileName, REVERSAL_FILE_EXTN);

	//jrd spqlog018
	//START: This is fix for the backup file not getting cleared when the reversal generated is bcoz of MTI/ mismatch
	if(inChkFileExist(szDestReversalFielName) == VS_SUCCESS)
	{
		remove(szDestReversalFielName);
	}
      //END: This is fix for the backup file not getting cleared when the reversal generated is bcoz of MTI mismatch


    file_copy(szSourceReversalFileName, szDestReversalFielName);


    obPacket.pchSendBuff = pstReqBuf;
    obPacket.inSendSize = inReqSiz;
    obPacket.inReceiveBuffSize = inRespSiz;
    obPacket.pchReceiveBuff = pstRespBuf;
    if (inMode == TXRX) {
        if (obCommunication.inSend) {
		BT_REQUEST_TRACE('B', obPacket.pchSendBuff, obPacket.inSendSize);
		//inWriteISO8583PacketToLog(obPacket.pchSendBuff, obPacket.inSendSize);
		#ifdef PRINTISO_DEFINED //jrd 01052004
		if (inPrintISO)
			inPrintISOPacket(VS_TRUE,obPacket.pchSendBuff , obPacket.inSendSize);
		#endif /* PRINTISO_DEFINED */

            inRetVal = obCommunication.inSend(&obCommunication, (char *) obPacket.pchSendBuff, obPacket.inSendSize, VS_FALSE, SEND_COMM_TIMEOUT, TRANSMITTING_MSG21);
            if ((inRetVal == E_NOCARRIER) || (inRetVal == E_X_NOCARRIER) || (inRetVal == VS_CARRIER))
                fCarrierPresent = VS_FALSE;
            if (inRetVal != inReqSiz) {
                pdebug(("inRetVal=%d", inRetVal));
                inRetVal = TR_WR_FAIL;
            }
        }
    }

    inTimeOut = inRespTimeout * 100; /* calc required for ACT library function (xmdm_receive_data)*/
    if (inRetVal >= 0)
        if (obCommunication.inReceive) {
            inRetVal = obCommunication.inReceive(&obCommunication, (char *) obPacket.pchReceiveBuff, obPacket.inReceiveBuffSize, inTimeOut, RECEIVING_MSG21);
		if(inRetVal > 0)
		{
	        	BT_RESPONSE_TRACE('B', obPacket.pchReceiveBuff, inRetVal);
			//inWriteISO8583PacketToLog(obPacket.pchReceiveBuff, inRetVal);
			#ifdef PRINTISO_DEFINED	//jrd 01052004
			if (inPrintISO)
				inPrintISOPacket(VS_FALSE,obPacket.pchReceiveBuff , inRetVal);
			#endif /* PRINTISO_DEFINED */
		}
        }

    if (fCarrierPresent == VS_FALSE) {
        pdebug(("!fCarrierPresent"));
        inRetVal = TR_TO_CARRIER;
    } else if ((inRetVal == E_NOCARRIER) || (inRetVal == E_X_NOCARRIER) || (inRetVal == VS_CARRIER)) {
        pdebug(("inRetVal=%d", inRetVal));
        inRetVal = TR_LOST_CARRIER;
    } else if (inRetVal <= 0) {
        pdebug(("TR_TO_RESPONSE"));
        inRetVal = TR_TO_RESPONSE;
    }

    return(inRetVal);
}

/*********************************************************************************************
* @func int | inBaseValidationLow |
* Validate ISO structure  and sends PIP transaction
*
* @parm VALIDATION_STRUCT * | psrRespValStruct |
*       Validation structure.
*
* @parm int | dummy |
*       Dummy value
*
* @rdesc Returns the success.
* @flag int | PIP Engine Return Value for the last uploaded host.
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inBaseValidationLow(VALIDATION_STRUCT* psrRespValStruct,int dummy) {
    BYTE bLocalString[3];
    int inRetVal;

    bLocalString[0] = 0x08;
    bLocalString[1] = 0x20;

    /* if amex host is not up */

    if (psrRespValStruct->comm_struct->receive[5] == 0x52)
        inRetVal = PIP_NOT_ONLINE;

    /*     If we received 0820, the return value will be -49 else
     *     an 0820 was not received
     */

    else if (memcmp(psrRespValStruct->comm_struct->p_fld_table[1].reference, bLocalString, 2) == 0)
        inRetVal = 60;
    else
        inRetVal = 0;

    return (inRetVal);
}

/*********************************************************************************************
* @func int | inBaseRespValidation |
* This routine checks the response against the following
* fields that are stored in the validation structure and is
* called by the PIP Engine.  The pointer to this function
* is passed to the PIP Engine in the PIP Engine Communications
* Data Structure (COMM_8583_DATA).
*
* @parm VALIDATION_STRUCT * | psrRespValStruct |
*       Validation structure.
*
* @parm int | inInternalVal |
*       Not used
*
* @rdesc Returns the success.
* @flag int | PIP Engine Return Value for the last uploaded host.
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inBaseRespValidation(VALIDATION_STRUCT* psrRespValStruct,int  inInternalVal) {
    VALIDATION_STRUCT* psrValStruct;
    VALIDATION_STRUCT srLocalValStruct;
    VALIDATION_STRUCT* psrValidStruct;
    int inRetVal = 0;
    field_struct* psrFieldArray;


    /*    Check for please wait message "0820" and Amex hangup
       string. */

    /* PIP engine calls this function with a void pointer instead of a sturcture pointer */

    psrValidStruct = (VALIDATION_STRUCT *) psrRespValStruct;
    if ((inRetVal = inBaseValidationLow(psrValidStruct, 0)) != 0)
        return (inRetVal);

    /*     If processing the reversal, the amount, trace #, and
        tid are located in the first 29 bytes of the store
        buffer.  Read this data into the local validation struct
        for validation.
    */

    if (psrValidStruct->comm_struct->state > TRAN_REQ) {
        memcpy(&srLocalValStruct, psrValidStruct->comm_struct->reversal, psrValidStruct->comm_struct->v_parms_size);

        srLocalValStruct.p_amount = psrValidStruct->p_amount;
        srLocalValStruct.p_tid = psrValidStruct->p_tid;
        srLocalValStruct.p_trace = psrValidStruct->p_trace;
        psrValStruct = &srLocalValStruct;
    } else {
        memcpy(&srLocalValStruct, psrValidStruct->comm_struct->transmit, psrValidStruct->comm_struct->v_parms_size);
        srLocalValStruct.p_amount = psrValidStruct->p_amount;
        srLocalValStruct.p_tid = psrValidStruct->p_tid;
        srLocalValStruct.p_trace = psrValidStruct->p_trace;
        psrValStruct = &srLocalValStruct;
    }

    vdTrimLeadZeroes((char *) psrValStruct->b_amount);
    vdTrimLeadZeroes((char *) psrValidStruct->p_amount);
    pad((char *) psrValStruct->b_tid, (char *) psrValStruct->b_tid, ' ', TID_SIZE, LEFT);
    pad((char *) psrValStruct->p_tid, (char *) psrValStruct->p_tid, ' ', TID_SIZE, LEFT);

    if (map_test(stMap8583, 41)) {
        if (strcmp((char *) psrValStruct->b_tid, (char *) psrValidStruct->p_tid))
            inRetVal = RETRY_CONTROL_TIMEOUT;
    }

    if (map_test(stMap8583, 11)) {
        if (psrValStruct->b_trace != *(psrValidStruct->p_trace))
            inRetVal = RETRY_CONTROL_TIMEOUT;
    }
    if (strcmp((char *) psrValStruct->b_amount, (char *) psrValidStruct->p_amount))
        inRetVal = RETRY_CONTROL_TIMEOUT;
    /* if reversal response - check for dcp and return an error
     * code to tell protocol level to stop processing.  This error
     * code is returned to the host level and is used to generate
     * a Reversal Advice (0420).
     */

    if (inRetVal != RETRY_CONTROL_TIMEOUT) {
        if ((inRetVal = check_8583_tpdu_msg_id(psrValidStruct->comm_struct, (unsigned char *) psrValidStruct->comm_struct->p_fld_table[1].reference, (unsigned char *) "\004\000")) > -50) {
            /***
            Look at the response code to the reversal request and determine
            if it is approved (=="00"). If it is not, then return with error.
            This way, the reversal will not be deleted.
            ***/
            psrFieldArray = (field_struct *) find_field_index(39, psrValidStruct->comm_struct->p_fld_table);

            if (strcmp((const char *) psrFieldArray->reference, "00"))
                return(-1);

            psrFieldArray = (field_struct *) find_field_index(44, psrValidStruct->comm_struct->p_fld_table);

            /* inRetVal will equal -75 when dcp approves a pending
             * reversal and -76 when dcp approves a new reversal
             */
            if (!(strcmp((const char *) psrFieldArray->reference, "02")) && map_test(psrValidStruct->comm_struct->map, 44))
                inRetVal = AMEX_DCP_REVERSAL - psrValidStruct->comm_struct->state;
            else
                inRetVal = 0;
        } else
            inRetVal = 0;
    }


    return(inRetVal);
}

/*********************************************************************************************
* @func int | inBaseRespValidationWithDupChk |
* This routine checks the response against the following
* fields that are stored in the validation structure and is
* called by the PIP Engine.  The pointer to this function
* is passed to the PIP Engine in the PIP Engine Communications
* Data Structure (COMM_8583_DATA).
*
* @parm VALIDATION_STRUCT * | psrRespValStruct |
*       Validation structure.
*
* @parm int | inInternalVal |
*       Not used
*
* @rdesc Returns the success.
* @flag int | PIP Engine Return Value for the last uploaded host.
* @flag int | VS_ERR
* @end
**********************************************************************************************/

int inBaseRespValidationWithDupChk(VALIDATION_STRUCT* psrRespValStruct,int  inInternalVal) {
    VALIDATION_STRUCT* psrValStruct;
    VALIDATION_STRUCT srLocalValStruct;
    VALIDATION_STRUCT* psrValidStruct;
    int inRetVal = 0;
    field_struct* psrFieldArray;


    /*    Check for please wait message "0820" and Amex hangup
       string. */

    /* PIP engine calls this function with a void pointer instead of a sturcture pointer */

    psrValidStruct = (VALIDATION_STRUCT *) psrRespValStruct;
    if ((inRetVal = inBaseValidationLow(psrValidStruct, 0)) != 0)
        return (inRetVal);

    /*     If processing the reversal, the amount, trace #, and
        tid are located in the first 29 bytes of the store
        buffer.  Read this data into the local validation struct
        for validation.
    */

    if (psrValidStruct->comm_struct->state > TRAN_REQ) {
        memcpy(&srLocalValStruct, psrValidStruct->comm_struct->reversal, psrValidStruct->comm_struct->v_parms_size);

        srLocalValStruct.p_amount = psrValidStruct->p_amount;
        srLocalValStruct.p_tid = psrValidStruct->p_tid;
        srLocalValStruct.p_trace = psrValidStruct->p_trace;
        psrValStruct = &srLocalValStruct;
    } else {
        memcpy(&srLocalValStruct, psrValidStruct->comm_struct->transmit, psrValidStruct->comm_struct->v_parms_size);
        srLocalValStruct.p_amount = psrValidStruct->p_amount;
        srLocalValStruct.p_tid = psrValidStruct->p_tid;
        srLocalValStruct.p_trace = psrValidStruct->p_trace;
        psrValStruct = &srLocalValStruct;
    }

    vdTrimLeadZeroes((char *) psrValStruct->b_amount);
    vdTrimLeadZeroes((char *) psrValidStruct->p_amount);
    pad((char *) psrValStruct->b_tid, (char *) psrValStruct->b_tid, ' ', TID_SIZE, LEFT);
    pad((char *) psrValStruct->p_tid, (char *) psrValStruct->p_tid, ' ', TID_SIZE, LEFT);

    if (map_test(stMap8583, 41)) {
        if (strcmp((char *) psrValStruct->b_tid, (char *) psrValidStruct->p_tid))
            inRetVal = RETRY_CONTROL_TIMEOUT;
    }

    if (map_test(stMap8583, 11)) {
        if (psrValStruct->b_trace != *(psrValidStruct->p_trace))
            inRetVal = RETRY_CONTROL_TIMEOUT;
    }
    if (strcmp((char *) psrValStruct->b_amount, (char *) psrValidStruct->p_amount))
        inRetVal = RETRY_CONTROL_TIMEOUT;
    /* if reversal response - check for dcp and return an error
     * code to tell protocol level to stop processing.  This error
     * code is returned to the host level and is used to generate
     * a Reversal Advice (0420).
     */

    if (inRetVal != RETRY_CONTROL_TIMEOUT) {
        if ((inRetVal = check_8583_tpdu_msg_id(psrValidStruct->comm_struct, (unsigned char *) psrValidStruct->comm_struct->p_fld_table[1].reference, (unsigned char *) "\004\000")) > -50) {
            /***
            Look at the response code to the reversal request and determine
            if it is approved (=="00"). If it is not, then return with error.
            This way, the reversal will not be deleted.
            ***/
            psrFieldArray = (field_struct *) find_field_index(39, psrValidStruct->comm_struct->p_fld_table);

            if (strcmp((const char *) psrFieldArray->reference, "00"))
                return(-1);

            psrFieldArray = (field_struct *) find_field_index(44, psrValidStruct->comm_struct->p_fld_table);

            /* inRetVal will equal -75 when dcp approves a pending
             * reversal and -76 when dcp approves a new reversal
             */
            if (!(strcmp((const char *) psrFieldArray->reference, "02")) && map_test(psrValidStruct->comm_struct->map, 44))
                inRetVal = AMEX_DCP_REVERSAL - psrValidStruct->comm_struct->state;
            else
                inRetVal = 0;
        } else
            inRetVal = 0;


        if ((inRetVal = check_8583_tpdu_msg_id(psrValidStruct->comm_struct, (unsigned char *) psrValidStruct->comm_struct->p_fld_table[1].reference, (unsigned char *) "\002\020")) > -50) {
            /***
            Look at the response code to the advice request and determine
            if it is a duplicate (=="94"). If it is set the response code to "00"
            so the advice record will be deleted.
            ***/
            psrFieldArray = (field_struct *) find_field_index(39, psrValidStruct->comm_struct->p_fld_table);

            if (!strcmp((const char *) psrFieldArray->reference, "94"))
                strncpy((char *) psrFieldArray->reference, "00", 2);

            inRetVal = 0;
        }
    }


    return(inRetVal);
}


int ISOUTL_CODE_CHECK(char* a,char* b,short* c,char* d,unsigned char* e) {
    GET_VER(a, b, c, d, e);
    return 1;
}

void vdSet64BitMapStop(unsigned char* pszField64) {
    field_struct srFieldISOFDT;

    srFieldISOFDT.field_num = 64 + STOP;
    srFieldISOFDT.packet_sz = 16;
    srFieldISOFDT.convert_idx = BCD_STR;
    srFieldISOFDT.reference = pszField64;
    srFieldISOFDT.var_sz = FIELD64_SIZE + 1;

    vdOverLoadISOFDT(FIELD64_POSITION, &srFieldISOFDT);
}

void vdReset64BitMapStop(unsigned char* pszField64) {
    field_struct srFieldISOFDT;

    srFieldISOFDT.field_num = 64;
    srFieldISOFDT.packet_sz = 16;
    srFieldISOFDT.convert_idx = BCD_STR;
    srFieldISOFDT.reference = pszField64;
    srFieldISOFDT.var_sz = FIELD64_SIZE + 1;

    vdOverLoadISOFDT(FIELD64_POSITION, &srFieldISOFDT);
}


#endif /* PIP_DEFINED */

#undef VSISUT_C

